package cn.sc.summer.mybatis.strategy.basestage;

import cn.hutool.core.collection.CollUtil;
import cn.sc.summer.mybatis.model.*;
import cn.sc.summer.mybatis.table.event.ColumnEvent;
import cn.sc.summer.mybatis.table.event.PrimaryEvent;
import cn.sc.summer.mybatis.table.event.TableEvent;
import cn.sc.summer.mybatis.constant.TableResource;
import cn.sc.summer.mybatis.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 类名：数据库表操作类型
 *
 * @author a-xin
 * @date 2024/8/28 12:28
 */
@Slf4j
public abstract class Event extends TableLog implements PrimaryEvent, TableEvent, ColumnEvent {

    private static final long serialVersionUID = 6917454632398384064L;

    /**
     * 数据源连接工具
     */
    public JdbcTemplate jdbcTemplate;

    /**
     * sql解析工具类
     */
    public SqlUtil sqlUtil;

    /**
     * 当前执行数据源信息
     */
    public DataSourceX dataSourceX;

    public void setJdbcTemplate(DataSourceX dataSourceX, SqlUtil sqlUtil) {
        this.dataSourceX = dataSourceX;
        this.jdbcTemplate = new JdbcTemplate(dataSourceX);
        this.sqlUtil = sqlUtil;
    }

    /**
     * 更新数据库表主键信息
     *
     * @param tablePrimaries 主键信息
     */
    public void updatePrimaryId(List<TablePrimary> tablePrimaries) {
        if (CollUtil.isNotEmpty(tablePrimaries)) {
            String updatePrimaryIdSql = sqlUtil.getUpdatePrimaryIdSql(tablePrimaries);
            print(updatePrimaryIdSql);
            this.jdbcTemplate.update(updatePrimaryIdSql);
        }
    }

    /**
     * 更新表信息
     *
     * @param tableBaseXInfo 表数据信息
     */
    public void updateTable(List<? extends TableUpdateInfo> tableBaseXInfo) {
        if (CollUtil.isNotEmpty(tableBaseXInfo)) {
            tableBaseXInfo.stream().forEach(item -> {
                String tableUpdateSql = sqlUtil.getTableUpdateSql(item.getTableName(), item.getTableComment());
                this.print(item.getTableName(), tableUpdateSql);
                this.jdbcTemplate.update(tableUpdateSql);
            });
        }
    }

    /**
     * 新增表信息
     *
     * @param tableBaseXInfo 表数据信息
     */
    public void addTable(List<? extends TableXInfo> tableBaseXInfo) {
        if (CollUtil.isNotEmpty(tableBaseXInfo)) {
            TableBaseConfig tableConfig = getTableConfig();
            tableBaseXInfo.stream().forEach(tableXInfo -> {
                List<TableFieldXInfo> tableFieldXInfos = tableXInfo.getTableFieldXInfos();

                List<String> primary = new ArrayList<>();
                String fieldSql = tableFieldXInfos.stream().map(tableFieldXInfo -> {
                    if (tableFieldXInfo.getPrimary()) {
                        primary.add(tableFieldXInfo.getFieldName());
                    }
                    return sqlUtil.getFieldSql(tableFieldXInfo.getFieldName(),
                            tableFieldXInfo.getFieldType(),
                            tableFieldXInfo.getComment(),
                            tableFieldXInfo.getNullable());
                }).collect(Collectors.joining(","));

                String tableName = tableXInfo.getTableName();
                String addSql = sqlUtil.getEnvSQL(tableConfig, tableName)
                        + sqlUtil.getTableAddSql(tableName, fieldSql, primary, tableXInfo.getComment(), tableConfig);

                this.print(tableName, addSql);
                this.jdbcTemplate.update(addSql);
            });
        }
    }

    /**
     * 删除表信息
     *
     * @param tableNames 表名称
     */
    public void delTable(List<String> tableNames) {
        if (CollUtil.isNotEmpty(tableNames)) {
            tableNames.stream().forEach(tableName -> {
                String tableDeleteSql = sqlUtil.getTableRenameSql(tableName, tableName + "_bak");
                this.print(tableName, tableDeleteSql);
                this.jdbcTemplate.update(tableDeleteSql);
            });
        }
    }

    /**
     * 新增表字段信息
     *
     * @param tableFieldXInfo 表字段信息
     */
    public void addColumn(List<? extends TableFieldXInfo> tableFieldXInfo) {
        if (CollUtil.isNotEmpty(tableFieldXInfo)) {
            tableFieldXInfo.stream().forEach(tableField -> {
                String fieldSql = sqlUtil.getFieldSql(tableField.getFieldName(),
                        tableField.getFieldType(),
                        tableField.getComment(),
                        tableField.getNullable());
                String fieldAddSql = sqlUtil.getFieldAddSql(tableField.getTableName(), fieldSql);
                this.print(tableField.getTableName(), fieldAddSql);
                this.jdbcTemplate.update(fieldAddSql);
            });
        }
    }

    /**
     * 更新表字段信息
     *
     * @param tableFieldXInfo 表字段信息
     */
    public void updateColumn(List<? extends TableFieldXInfo> tableFieldXInfo) {
        if (CollUtil.isNotEmpty(tableFieldXInfo)) {
            tableFieldXInfo.stream().forEach(tableField -> {
                String fieldSql = sqlUtil.getFieldSql(tableField.getFieldName(), tableField.getFieldType(), tableField.getComment(), tableField.getNullable());
                String fieldUpdateSql = sqlUtil.getFieldUpdateSql(tableField.getTableName(), fieldSql);
                this.print(tableField.getTableName(), fieldUpdateSql);
                this.jdbcTemplate.update(fieldUpdateSql);
            });
        }
    }

    /**
     * 删除表字段信息
     *
     * @param tableFieldDels 表字段信息
     */
    public void delColumn(List<? extends TableFieldDel> tableFieldDels) {
        if (CollUtil.isNotEmpty(tableFieldDels)) {
            tableFieldDels.stream().forEach(tableFieldDel -> {
                String fieldDeleteSql = sqlUtil.getFieldDeleteSql(tableFieldDel.getTableName(), tableFieldDel.getFieldName());
                this.print(tableFieldDel.getTableName(), fieldDeleteSql);
                this.jdbcTemplate.update(fieldDeleteSql);
            });
        }
    }

    /**
     * 确定该枚举类支持的数据源类型
     *
     * @return 支持的数据源类型
     */
    public abstract String supports();

    /**
     * 获取对应数据源类别的配置信息
     *
     * @return 数据源表配置信息
     */
    public TableBaseConfig getTableConfig() {
        String supports = getSupports();
        if (!TableResource.TABLE_CHARSET_INFO.containsKey(supports)) {
            throw new IllegalArgumentException("The corresponding data source [" + supports + "] configuration information does not exist!");
        }
        return TableResource.TABLE_CHARSET_INFO.get(supports);
    }

    private static String TABLE_PRINT = "";

    /**
     * sql日志打印
     *
     * @param tableName  表名称
     * @param executeSql 执行sql
     */
    public void print(String tableName, String executeSql) {
        String dataSourceName = dataSourceX.getDataSourceName();
        if (!TABLE_PRINT.equals(dataSourceName + tableName)) {
            TABLE_PRINT = dataSourceName + tableName;
            super.printTable(dataSourceX, tableName);
        }
        super.print(executeSql);
    }

}
